package com.way.capture.activity;

import android.Manifest;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.provider.Settings;
import com.google.android.material.snackbar.Snackbar;
import androidx.core.app.SharedElementCallback;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.michaelflisar.dragselectrecyclerview.DragSelectTouchListener;
import com.michaelflisar.dragselectrecyclerview.DragSelectionProcessor;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import com.way.capture.App;
import com.way.capture.R;
import com.way.capture.adapter.ScreenshotAdapter;
import com.way.capture.base.BaseActivity;
import com.way.capture.data.DataInfo;
import com.way.capture.utils.AppUtil;
import com.way.capture.utils.RxSchedulers;
import com.way.capture.utils.ScreenshotFileObserver;
import com.way.capture.utils.Utils;
import com.way.capture.widget.GridDividerItemDecoration;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;

public class MainActivity extends BaseActivity implements ActionMode.Callback,
        ScreenshotFileObserver.OnNewFileChangedListener {
    public static final String ALBUM_PATH = "ALBUM_PATH";
    public static final String EXTRA_CURRENT_ALBUM_POSITION = "EXTRA_CURRENT_ALBUM_POSITION";
    private static final String TAG = "MainActivity";
    protected View mLoadingView;
    protected View mEmptyView;
    protected View mErrorView;
    @BindView(R.id.recycler_view)
    RecyclerView mRecyclerView;
    @BindView(R.id.toolbar)
    Toolbar mToolbar;
    private ScreenshotAdapter mAdapter;
    private DragSelectTouchListener mDragSelectTouchListener;
    private ActionMode mActionMode;
    private ScreenshotFileObserver mFileObserver;
    private long mLastPressTime;
    private int mSharedElementReturnPosition = -1;

    private final SharedElementCallback mCallback = new SharedElementCallback() {
        @Override
        public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
            Log.d(TAG, "onMapSharedElements: fragment is null ? " + (mAdapter == null)
                    + ", fragment.getData.isEmpty = " + (mAdapter == null || mAdapter.getData().isEmpty())
                    + ", mSharedElementReturnPosition = " + mSharedElementReturnPosition);
            if (mSharedElementReturnPosition != -1 && mAdapter != null && mSharedElementReturnPosition < mAdapter.getData().size()) {
                String newTransitionName = mAdapter.getData().get(mSharedElementReturnPosition).path;
                View layout = mRecyclerView.findViewWithTag(newTransitionName);
                View newSharedElement = layout != null ? layout.findViewById(R.id.iv_image) : null;
                if (newSharedElement != null) {
                    names.clear();
                    names.add(newTransitionName);
                    sharedElements.clear();
                    sharedElements.put(newTransitionName, newSharedElement);
                }
                mSharedElementReturnPosition = -1;
            } else {
                View navigationBar = findViewById(android.R.id.navigationBarBackground);
                View statusBar = findViewById(android.R.id.statusBarBackground);
                if (navigationBar != null) {
                    names.add(navigationBar.getTransitionName());
                    sharedElements.put(navigationBar.getTransitionName(), navigationBar);
                }
                if (statusBar != null) {
                    names.add(statusBar.getTransitionName());
                    sharedElements.put(statusBar.getTransitionName(), statusBar);
                }
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (PreferenceManager.getDefaultSharedPreferences(this)
                .getBoolean(AppUtil.APP_FIRST_RUN, true)) {
            startActivity(new Intent(this, GuideActivity.class));
        }
        Log.d(TAG, "onCreate: ");
        setExitSharedElementCallback(mCallback);
        setSupportActionBar(mToolbar);
        LayoutInflater inflater = getLayoutInflater();
        mLoadingView = inflater.inflate(R.layout._loading_layout_loading, null);
        mEmptyView = inflater.inflate(R.layout._loading_layout_empty, null);
        mErrorView = inflater.inflate(R.layout._loading_layout_error, null);
        mErrorView.findViewById(R.id.retry_button).setOnClickListener(v -> {
            int error = (int) mErrorView.getTag();
            if (error == 0) {
                showRequestPermissionDialog();
            } else if (error == 1) {
                gotoSettings();
            } else {
                loadData();
            }
        });

        GridLayoutManager layoutManager = new GridLayoutManager(this, 4);
        mRecyclerView.addItemDecoration(new GridDividerItemDecoration(Utils.dp2px(2),
                ContextCompat.getColor(this, android.R.color.transparent)));
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(layoutManager);
        mAdapter = new ScreenshotAdapter(R.layout.item_screenshot);

        mRecyclerView.setAdapter(mAdapter);

        mAdapter.setOnItemClickListener((adapter, view, position) -> {
            if (mActionMode != null) {
                mAdapter.toggleSelection(position);
                mActionMode.setTitle(getString(R.string.cab_title_x, mAdapter.getCountSelected()));
            } else {
                ImageView imageView = view.findViewById(R.id.iv_image);
                ArrayList<DataInfo> lists = new ArrayList<>(mAdapter.getData());
                DetailsActivity.start(this, imageView, lists, position);
            }
        });
        mAdapter.setOnItemLongClickListener((adapter, view, position) -> {
            mDragSelectTouchListener.startDragSelection(position);
            return false;
        });
        DragSelectionProcessor dragSelectionProcessor = new DragSelectionProcessor(new DragSelectionProcessor.ISelectionHandler() {
            @Override
            public HashSet<Integer> getSelection() {
                return mAdapter.getSelection();
            }

            @Override
            public boolean isSelected(int index) {
                return mAdapter.getSelection().contains(index);
            }

            @Override
            public void updateSelection(int start, int end, boolean isSelected, boolean calledFromOnStart) {
                mAdapter.selectRange(start, end, isSelected);
                Log.d(TAG, "updateSelection: ");
                if (getSelection().isEmpty()) {
                    mActionMode.finish();
                } else {
                    if (mActionMode == null) {
                        mActionMode = mToolbar.startActionMode(MainActivity.this);
                    }
                    mActionMode.setTitle(getString(R.string.cab_title_x, getSelection().size()));
                }
            }
        }).withMode(DragSelectionProcessor.Mode.Simple);
        mDragSelectTouchListener = new DragSelectTouchListener()
                .withSelectListener(dragSelectionProcessor)
                .withBottomOffset(-Utils.getNavigationBarHeight());
        mRecyclerView.addOnItemTouchListener(mDragSelectTouchListener);
        loadData();
        mFileObserver = new ScreenshotFileObserver(AppUtil.SCREENSHOT_FOLDER_PATH, this);
        mFileObserver.startWatching();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
        mFileObserver.stopWatching();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart: ");
        //loadData();
    }

    private void loadData() {
        if (mAdapter != null) {
            mAdapter.setEmptyView(mLoadingView);
        }
        mSubscriptions.add(new RxPermissions(this)
                .requestEachCombined(Manifest.permission.WRITE_EXTERNAL_STORAGE)
                .observeOn(AndroidSchedulers.mainThread())
                .concatMap((Function<Permission, ObservableSource<List<DataInfo>>>) permission -> {
                    if (permission.granted) {
                        return Observable.create(e -> {
                            e.onNext(DataInfo.getDatas());
                            e.onComplete();
                        });
                    } else if (permission.shouldShowRequestPermissionRationale) {
                        Log.d(TAG, "loadData: shouldShowRequestPermissionRationale");
                        mErrorView.setTag(0);
                        throw new Exception(getString(R.string.permission_error));
                    } else {
                        Log.d(TAG, "loadData: never ask");
                        mErrorView.setTag(1);
                        throw new Exception(getString(R.string.permission_error));
                    }
                })
                .compose(RxSchedulers.io_main())
                .subscribe(this::onLoadFinished, this::onError));
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: ");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: ");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ");
    }

    @Override
    public void onActivityReenter(int resultCode, Intent data) {
        super.onActivityReenter(resultCode, data);
        if (data != null) {
            mSharedElementReturnPosition = data.getIntExtra(EXTRA_CURRENT_ALBUM_POSITION, -1);
            Log.d(TAG, "onActivityReenter: fragment is null ? " + (mAdapter == null)
                    + ", fragment.getData.isEmpty = " + (mAdapter == null || mAdapter.getData().isEmpty())
                    + ", mSharedElementReturnPosition = " + mSharedElementReturnPosition);

            if (mSharedElementReturnPosition > -1 && mAdapter != null && mSharedElementReturnPosition < mAdapter.getData().size()) {
                DataInfo albumItem = mAdapter.getData().get(mSharedElementReturnPosition);
                albumItem.isSharedElement = true;
                postponeEnterTransition();
                mRecyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                    @Override
                    public void onLayoutChange(View v, int l, int t, int r, int b,
                                               int oL, int oT, int oR, int oB) {
                        mRecyclerView.removeOnLayoutChangeListener(this);
                        startPostponedEnterTransition();
                    }
                });
                mRecyclerView.scrollToPosition(mSharedElementReturnPosition);
            }
        }

    }

    @Override
    protected int getContentView() {
        return R.layout.activity_main;
    }

    @Override
    public void onBackPressed() {
        long time = System.currentTimeMillis();
        if (time - mLastPressTime > 3000) {
            Snackbar.make(mRecyclerView, R.string.twice_press_exit, Snackbar.LENGTH_LONG).show();
            mLastPressTime = time;
        } else {
            finish();
            //super.onBackPressed();
        }
    }

    public void onLoadFinished(List<DataInfo> data) {
        if (!data.isEmpty()) {
            mAdapter.setNewData(data);
        } else {
            mAdapter.clearData();
            mAdapter.setEmptyView(mEmptyView);
        }
    }

    public void onError(Throwable e) {
        if (mAdapter != null) {
            mAdapter.clearData();
            TextView textView = mErrorView.findViewById(R.id.error_title);
            textView.setText(e.getMessage());
            mAdapter.setEmptyView(mErrorView);
        }
    }

    private void syncNightMode(MenuItem item) {
        int uiMode = getResources().getConfiguration().uiMode;
        boolean isCurrentNightMode = (uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
        item.setIcon(isCurrentNightMode ? R.drawable.ic_day_mode : R.drawable.ic_night_mode);
        item.setTitle(isCurrentNightMode ? R.string.nav_day_mode : R.string.nav_night_mode);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        MenuItem item = menu.findItem(R.id.action_night_mode);
        syncNightMode(item);
        return true;
    }

    public void reboot() {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        finish();
        overridePendingTransition(0, android.R.anim.fade_out);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.action_night_mode:
                item.setEnabled(false);
                mSharedElementReturnPosition = -1;
                final boolean isNightMode = com.way.capture.utils.Settings.getInstance().isNightMode();
                Log.i(TAG, "isNightMode = " + isNightMode);
                com.way.capture.utils.Settings.getInstance().setNightMode(!isNightMode);
                reboot();
                return true;
/*            case R.id.action_share:
                String url = "http://fir.im/capturer";
                url = getString(R.string.share_app, url);
                Intent sharingIntent = new Intent(Intent.ACTION_SEND);
                sharingIntent.setType("text/plain");
                sharingIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
                sharingIntent.putExtra(Intent.EXTRA_TEXT, url);
                sharingIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                Intent chooserIntent = Intent.createChooser(sharingIntent, null);
                startActivity(chooserIntent);
                break;*/
            case R.id.action_settings:
                startActivity(new Intent(MainActivity.this, SettingsActivity.class));
                return true;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    private void showRequestPermissionDialog() {
        new AlertDialog.Builder(this).setTitle(R.string.permission_title)
                .setCancelable(false)
                .setMessage(R.string.required_permissions_promo)
                .setNegativeButton(android.R.string.cancel, null)
                .setPositiveButton(android.R.string.ok, (dialog, which) -> {
                    loadData();
                }).show();
    }

    private void gotoSettings() {
        new AlertDialog.Builder(this).setTitle(R.string.permission_title)
                .setCancelable(false)
                .setMessage(R.string.enable_permission_procedure)
                .setNegativeButton(android.R.string.cancel, null)
                .setPositiveButton(android.R.string.ok, (dialog, which) -> {
                    final Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                            Uri.parse(Utils.PACKAGE_URI_PREFIX + getPackageName()));
                    startActivity(intent);
                }).show();
    }

    @Override
    public void onNewFileChanged(String path) {
        DataInfo dataInfo = DataInfo.getDataInfo(-1, path);
        AndroidSchedulers.mainThread().scheduleDirect(() -> {
            if (dataInfo != null) {
                mAdapter.addData(0, dataInfo);
                mAdapter.notifyDataSetChanged();
            }
        });
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mode.getMenuInflater().inflate(R.menu.menu_main_actionmode, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        HashSet<Integer> selections = mAdapter.getSelection();
        switch (item.getItemId()) {
            case R.id.image_delete:
                List<DataInfo> dataInfos = new ArrayList<>();
                for (int index : selections) {
                    dataInfos.add(mAdapter.getItem(index));
                }
                mAdapter.removeMulData(dataInfos);
                mAdapter.deselectAll();
                AppUtil.deleteMultipleScreenshot(App.getContext(), dataInfos);// TODO: 2018/4/6 should in thread!!
                mActionMode.finish();
                if (mAdapter.getItemCount() < 1) {
                    mAdapter.clearData();
                    mAdapter.setEmptyView(mEmptyView);
                }
                break;

            case R.id.image_select_all:
                if (!item.isChecked()) {
                    mAdapter.selectAll();
                    mActionMode.setTitle(getString(R.string.cab_title_x, mAdapter.getSelection().size()));
                    item.setTitle(R.string.clear_all);
                    item.setChecked(true);
                } else {
                    mActionMode.finish();
                    mAdapter.deselectAll();
                    item.setChecked(false);
                }
                break;
        }
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mAdapter.deselectAll();
        mActionMode = null;
    }
}
